package cn.util;

import cn.TCSP;
import cn.wetcland.base.WetclandScoreBoard;
import cn.wetcland.dao.WetclandPlayerDao;
import cn.wetcland.pojo.WetclandPlayer;
import cn.wetcland.thread.HologramThread;
import multiworld.ConfigException;
import multiworld.MultiWorldPlugin;
import multiworld.WorldGenException;
import multiworld.api.MultiWorldAPI;
import multiworld.data.DataHandler;
import multiworld.data.InternalWorld;
import multiworld.data.WorldContainer;
import multiworld.data.WorldUtils;
import multiworld.worldgen.WorldGenerator;
import net.minecraft.server.v1_16_R3.NBTCompressedStreamTools;
import net.minecraft.server.v1_16_R3.NBTTagCompound;
import org.apache.ibatis.session.SqlSession;
import org.bukkit.Bukkit;
import org.bukkit.GameRule;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.attribute.Attribute;
import org.bukkit.attribute.AttributeInstance;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftItemStack;
import org.bukkit.entity.*;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginManager;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.*;

public class TCUtil {

    public static WetclandPlayer getAttrPlayer(String playername) {
        Map<String, Object> map = (Map<String, Object>) TCSP.getPlayerAttr().get(playername);
        return (WetclandPlayer) map.get("info");
    }

    public static HologramThread getAttrPlayerHologram(String playername) {
        Map<String, Object> map = (Map<String, Object>) TCSP.getPlayerAttr().get(playername);
        return (HologramThread) map.get("holo");
    }

    public static boolean getAttrPlayerLRStatus(String playername) {
        Map<String, Object> map = (Map<String, Object>) TCSP.getPlayerAttr().get(playername);
        return (boolean) map.get("lr");
    }

    public static WetclandScoreBoard getAttrWetclandScoreBoard(String playername) {
        Map<String, Object> map = (Map<String, Object>) TCSP.getPlayerAttr().get(playername);
        return (WetclandScoreBoard) map.get("wsb");
    }

    public static String getStringWorld(String worldname) {
        switch (worldname) {
            case "world":
                return "主城";
            case "SuperPlot":
                return "景秀";
            case "PlotWorld":
                return "世家";
            case "ResWorld":
                return "资源";
            case "world_nether":
                return "地狱";
            case "world_the_end":
                return "末地";
        }
        return "NULL";
    }

    /**
     * 设置服务器所有世界的游戏规则
     */
    public static void setServerWorldsGameRule() {
        List<World> worldList = Bukkit.getWorlds();
        for (World world : worldList) {
            // 玩家死亡后是否保留物品栏物品 (死亡时物品不掉落).
            world.setGameRule(GameRule.KEEP_INVENTORY, true);
            // 玩家死亡时是否不显示死亡界面直接重生.
            world.setGameRule(GameRule.DO_IMMEDIATE_RESPAWN, true);
            // 火是否蔓延及自然熄灭.
            world.setGameRule(GameRule.DO_FIRE_TICK, false);
            // 是否爆炸破坏地形
            world.setGameRule(GameRule.MOB_GRIEFING, false);
        }
    }

    public static String getMemberTypeString(int type) {
        switch (type) {
            case 1:
                return "VIP";
            case 2:
                return "SVIP";
            case 3:
                return "至尊SVIP";
        }
        return null;
    }

    public static String getStringLevel(int level) {
        switch (level) {
            case 1:
                return "列兵";
            case 2:
                return "下士";
            case 3:
                return "中士";
            case 4:
                return "上士";
            case 5:
                return "少尉";
            case 6:
                return "中尉";
            case 7:
                return "上尉";
            case 8:
                return "少校";
            case 9:
                return "中校";
            case 10:
                return "上校";
            case 11:
                return "将军";
            case 12:
                return "统帅";
            case 13:
                return "督军";
            case 14:
                return "大都督";
        }
        return "NULL";
    }

    public static void updatePlayerHealthByLevel(Player player, int level) {
        AttributeInstance attribute = player.getAttribute(Attribute.GENERIC_MAX_HEALTH);
        assert attribute != null;
        switch (level) {
            case 1:
                attribute.setBaseValue(22);
                break;
            case 2:
                attribute.setBaseValue(24);
                break;
            case 3:
                attribute.setBaseValue(26);
                break;
            case 4:
                attribute.setBaseValue(28);
                break;
            case 5:
                attribute.setBaseValue(30);
                break;
            case 6:
                attribute.setBaseValue(32);
                break;
            case 7:
                attribute.setBaseValue(34);
                break;
            case 8:
                attribute.setBaseValue(36);
                break;
            case 9:
                attribute.setBaseValue(38);
                break;
            case 10:
                attribute.setBaseValue(40);
                break;
        }
    }

    public static String getMonsterName(Mob monster) {
        if (monster instanceof PigZombie) {
            return "赤眼猪妖";
        } else if (monster instanceof Hoglin) {
            return "烛残";
        } else if (monster instanceof Drowned) {
            return "水鬼";
        } else if (monster instanceof Zoglin) {
            return "僵烛残";
        } else if (monster instanceof ZombieVillager) {
            return "僵仔";
        } else if (monster instanceof Husk) {
            return "阎尸";
        } else if (monster instanceof Stray) {
            return "娄郎";
        } else if (monster instanceof Zombie) {
            return "狌々";
        } else if (monster instanceof WitherSkeleton) {
            return "乌凋";
        } else if (monster instanceof Skeleton) {
            return "拘缨";
        } else if (monster instanceof Spider) {
            return "鬿誉";
        } else if (monster instanceof Creeper) {
            return "司幽";
        } else if (monster instanceof Enderman) {
            return "獬豸";
        } else if (monster instanceof Piglin) {
            return "奎";
        } else if (monster instanceof Blaze) {
            return "赤燸";
        } else if (monster instanceof ElderGuardian) {
            return "大海虫";
        } else if (monster instanceof Guardian) {
            return "小海虫";
        } else if (monster instanceof Endermite) {
            return "羫";
        } else if (monster instanceof Evoker) {
            return "猰貐";
        } else if (monster instanceof Ghast) {
            return "血怼";
        } else if (monster instanceof MagmaCube) {
            return "血滴子";
        } else if (monster instanceof Slime) {
            return "莱莱";
        } else if (monster instanceof Vex) {
            return "魂瑜";
        } else if (monster instanceof Vindicator) {
            return "觊觎";
        } else if (monster instanceof Witch) {
            return "药姑";
        }
        return monster.getName();
    }

    public static String randomServerMotdStr() {
        // 34字一行 MOTD
        String arr[] = {
                "§b♫♫♫欢迎来到§dWetcland§b服务器♫♫♫",
                "§b❀❀❀§aWetcland服务器§b欢迎您❀❀❀",
                "§c❤❤❤§bWetcland§c❤❤❤"
        };
        String inf[] = {
                "§a直连IP: wetcland.cn",
                "§a官方网站: wetcland.cn",
                "§a服务器每周一进行维护, 请悉知!",
                "§d请坚持每天签到哦, 奖励多多~",
                "§d资源/末地/地狱 每个月末进行重置~",
                "§d全球市场每天00:00进行市场更新",
                "§a请遵守服务器规则",
                "§a服主QQ: §d2974648933",
                "§a服务器QQ交流群: §d168986131"
        };
        Random random = new Random();
        int nextInt = random.nextInt(arr.length);
        int anInt = random.nextInt(inf.length);
        return arr[nextInt] + "\n" + inf[anInt];
    }

    public static void updateWetclandPlayerInDB(WetclandPlayer wetclandPlayer) {
        SqlSession sqlSession = TCSP.getSqlSessionFactory().openSession(true);
        WetclandPlayerDao mapper = sqlSession.getMapper(WetclandPlayerDao.class);
        mapper.updatePlayer(wetclandPlayer);
        sqlSession.close();
    }

    /**
     * 生成世界
     * @param worldName 世界名称
     * @param worldType 世界类型
     */
    public static void genWorld(String worldName, WorldGenerator worldType) {
        PluginManager pluginManager = Bukkit.getPluginManager();
        Plugin multiWorld = pluginManager.getPlugin("MultiWorld");
        try {
            DataHandler dataHandler = new DataHandler(multiWorld.getConfig(), (MultiWorldPlugin) multiWorld);
            WorldUtils worldManager = dataHandler.getWorldManager();
            WorldContainer worldContainer = worldManager.getWorldMeta(worldName, false);
            worldContainer.setLoaded(true);
            worldContainer.loadWorld();
            worldContainer.setWorld(worldManager.getInternalWorld(worldName, false));
            long seed = (new java.util.Random()).nextLong();
            worldManager.makeWorld(worldName, worldType, seed, "");
            dataHandler.scheduleSave();
        } catch (WorldGenException | ConfigException e) {
            e.printStackTrace();
        }
    }

    /**
     * 删除世界
     * @param worldName 世界名称
     */
    public static void deleteWorld(String worldName) {
        PluginManager pluginManager = Bukkit.getPluginManager();
        Plugin multiWorld = pluginManager.getPlugin("MultiWorld");
        try {
            DataHandler dataHandler = new DataHandler(multiWorld.getConfig(), (MultiWorldPlugin) multiWorld);
            WorldUtils worldManager = dataHandler.getWorldManager();
            WorldContainer worldContainer = worldManager.getWorldMeta(worldName, false);
            worldContainer.setLoaded(true);
            worldContainer.loadWorld();
            worldContainer.setWorld(worldManager.getInternalWorld(worldName, false));
            worldManager.unloadWorld(worldName);
            worldManager.deleteWorld(worldName);
            dataHandler.scheduleSave();
        } catch (ConfigException e) {
            e.printStackTrace();
        }
    }

    public static String remakeDirtyStr(String str) {
        return str.replaceAll("叼|日|FUCK|TM|TMD|tm|tmd|艹|草|傻|狗|混账|B的|b的|妈的", "*");
    }

    public static byte[] convertNBTToByteArr(ItemStack itemStack) {
        ByteArrayOutputStream byteArrayOutputStream = null;
        try {
            net.minecraft.server.v1_16_R3.ItemStack itemStack2 = CraftItemStack.asNMSCopy(itemStack);
            NBTTagCompound tag = itemStack2.save(new NBTTagCompound());
            byteArrayOutputStream = new ByteArrayOutputStream(1024);
            NBTCompressedStreamTools.a(tag, byteArrayOutputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return byteArrayOutputStream.toByteArray();
    }

    public static NBTTagCompound convertByteArrToNBT(byte[] bytes) {
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
        NBTTagCompound nbtTagCompound = null;
        try {
            nbtTagCompound = NBTCompressedStreamTools.readNBT(byteArrayInputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return nbtTagCompound;
    }

    public static void setItemStackNBT(ItemStack itemStack, NBTTagCompound nbtTagCompound) {
        net.minecraft.server.v1_16_R3.ItemStack itemStack1 = CraftItemStack.asNMSCopy(itemStack);
        itemStack1.setTag(nbtTagCompound);
    }

    public static ItemStack convertNBTTOItemStack(NBTTagCompound nbtTagCompound) {
        net.minecraft.server.v1_16_R3.ItemStack itemStack = net.minecraft.server.v1_16_R3.ItemStack.a(nbtTagCompound);
        return CraftItemStack.asBukkitCopy(itemStack);
    }

    public static int getMonthDay(int month) {
        if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 ||
                month == 10 || month == 12) {
            return 31;
        } else if (month == 4 || month == 6 || month == 9 || month == 11) {
            return 30;
        } else {
            //判断任意年份是否为闰年，需要满足以下条件中的任意一个：
            //① 该年份能被 4 整除同时不能被 100 整除；
            //② 该年份能被400整除。
            //闰年2月 29天，平年28天
            int year = Calendar.getInstance().get(Calendar.YEAR);
            if ((year % 400 == 0) || (year % 4 == 0 && year % 100 != 0)) {
                return 29;
            } else {
                return 28;
            }
        }
    }

    /**
     * 指定玩家签到并保存到文件
     *
     * @param playerName 签到的玩家名称
     * @return 最大连续签到次数
     */
    public static int signInAndSaveYaml(String playerName) {
        YamlConfiguration signInYaml = TCSP.getSignInYaml();
        Calendar instance = Calendar.getInstance();
        int year = instance.get(Calendar.YEAR);
        int month = instance.get(Calendar.MONTH) + 1;
        int dayOfMonth = instance.get(Calendar.DAY_OF_MONTH);
        // 记录最大连续签到次数
        int maxLen = 0, nowLen = 1;
        List<Integer> list = getSignInYaml(playerName);
        if (list == null) {
            list = new ArrayList<>();
        }
        list.add(dayOfMonth);
        // 格式： 玩家名称.年份.月份
        signInYaml.set(playerName + "." + year + "." + month, list);
        try {
            signInYaml.save("PlayerData/SignIn.yml");
        } catch (IOException e) {
            e.printStackTrace();
        }
        for (int i = 1; i < list.size(); i++) {
            if (list.get(i) - list.get(i - 1) == 1) {
                nowLen++;
            } else {
                if (maxLen < nowLen) {
                    maxLen = nowLen;
                }
                nowLen = 1;
            }
        }
        if (maxLen < nowLen) {
            maxLen = nowLen;
        }
        return maxLen;
    }

    /**
     * 获得指定玩家签到记录集合
     * @param playerName 玩家名称
     * @return 签到记录集合
     */
    public static List<Integer> getSignInYaml(String playerName) {
        YamlConfiguration signInYaml = TCSP.getSignInYaml();
        Calendar instance = Calendar.getInstance();
        int year = instance.get(Calendar.YEAR);
        int month = instance.get(Calendar.MONTH) + 1;
        List<Integer> integerList = signInYaml.getIntegerList(playerName + "." + year + "." + month);
        return integerList;
    }

    /**
     * 保存位置信息到文件
     * @param locationName 位置名称
     * @param location 位置实例
     */
    public static void saveLocationInYaml(String locationName, Location location) {
        YamlConfiguration serverBasicYaml = TCSP.getServerBasicYaml();
        serverBasicYaml.set("locations." + locationName, location);
        try {
            serverBasicYaml.save("WetclandServer/serverBasic.yml");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 用位置名称得到位置实例
     * @param locationName 位置名称
     * @return 位置实例
     */
    public static Location getLocationByNameInYaml(String locationName) {
        YamlConfiguration serverBasicYaml = TCSP.getServerBasicYaml();
        Object o = serverBasicYaml.get("locations." + locationName);
        return (Location)o;
    }

    /**
     * 获取物品的强化等级
     *
     * @param itemStack 物品
     * @return 等级
     */
    public static int getItemIntensifierLevel(ItemStack itemStack) {
        ItemMeta itemMeta = itemStack.getItemMeta();
        List<String> lore = itemMeta.getLore();
        int level = 0;
        if (lore == null) return 0;
        for (int i = 0; i < lore.size(); i++) {
            if (lore.get(i).startsWith("§d强化等级") || lore.get(i).startsWith("§b强化等级")) {
                level = Integer.parseInt(lore.get(i).split("=")[1].trim());
                break;
            }
        }
        return level;
    }

    /**
     * 指定物品的强化等级
     *
     * @param itemStack 物品
     * @param level     指定等级
     */
    public static void setItemIntensifierLevel(ItemStack itemStack, int level) {
        ItemMeta itemMeta = itemStack.getItemMeta();
        List<String> lore = itemMeta.getLore();
        int flag = -1;
        if (lore == null) {
            ArrayList<String> strings = new ArrayList<>();
            strings.add("§d强化等级=" + level);
            itemMeta.setLore(strings);
            itemStack.setItemMeta(itemMeta);
            return;
        }
        for (int i = 0; i < lore.size(); i++) {
            if (lore.get(i).startsWith("§d强化等级=")) {
                flag = 1;
                lore.set(i, "§d强化等级=" + level);
                itemMeta.setLore(lore);
                itemStack.setItemMeta(itemMeta);
                break;
            }
        }
        if (flag == -1) {
            lore.add("§d强化等级=" + level);
            itemMeta.setLore(lore);
            itemStack.setItemMeta(itemMeta);
        }
    }

    /**
     * 获取指定物品的淬炼等级
     * @param itemStack 指定物品
     * @return 等级
     */
    public static int getItemRefinerLevel(ItemStack itemStack) {
        ItemMeta itemMeta = itemStack.getItemMeta();
        List<String> lore = itemMeta.getLore();
        int level = 0;
        if (lore == null) return 0;
        for (int i = 0; i < lore.size(); i++) {
            if (lore.get(i).startsWith("§d淬炼等级") || lore.get(i).startsWith("§b淬炼等级")) {
                level = Integer.parseInt(lore.get(i).split("=")[1].trim());
                break;
            }
        }
        return level;
    }

    /**
     * 指定物品的淬炼等级
     *
     * @param itemStack 物品
     * @param level     指定等级
     */
    public static void setItemRefinerLevel(ItemStack itemStack, int level) {
        ItemMeta itemMeta = itemStack.getItemMeta();
        List<String> lore = itemMeta.getLore();
        int flag = -1;
        if (lore == null) {
            ArrayList<String> strings = new ArrayList<>();
            strings.add("§d淬炼等级=" + level);
            itemMeta.setLore(strings);
            itemStack.setItemMeta(itemMeta);
            return;
        }
        for (int i = 0; i < lore.size(); i++) {
            if (lore.get(i).startsWith("§d淬炼等级=")) {
                flag = 1;
                lore.set(i, "§d淬炼等级=" + level);
                itemMeta.setLore(lore);
                itemStack.setItemMeta(itemMeta);
                break;
            }
        }
        if (flag == -1) {
            lore.add("§d淬炼等级=" + level);
            itemMeta.setLore(lore);
            itemStack.setItemMeta(itemMeta);
        }
    }
}
